home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / read.c < prev    next >
C/C++ Source or Header  |  1994-02-14  |  4KB  |  177 lines

  1. /*
  2.  * _read: like read, but takes a long instead of an int. Written by
  3.  * Eric R. Smith and placed in the public domain.
  4.  */
  5.  
  6. #include <fcntl.h>
  7. #include <osbind.h>
  8. #include <errno.h>
  9. #include <ioctl.h>
  10. #include <signal.h>
  11. #include <unistd.h>
  12. #include <support.h>
  13. #include <mintbind.h>
  14. #include "lib.h"
  15.  
  16. #define CTRL(x) (x & 0x1f)
  17. #define UNDEF -1
  18.  
  19. struct tchars __tchars = {
  20.     CTRL('C'),        /* interrupt */
  21.     CTRL('\\'),        /* quit */
  22.     CTRL('Q'),        /* start */
  23.     CTRL('S'),        /* stop */
  24.     CTRL('D'),        /* EOF */
  25.     '\r'            /* alternate end of line */
  26. };
  27.  
  28. struct ltchars __ltchars = {
  29.     CTRL('Z'),        /* suspend */
  30.     CTRL('Y'),        /* suspend after read */
  31.     CTRL('R'),        /* reprint */
  32.     UNDEF,            /* flush output */
  33.     UNDEF,            /* erase word */
  34.     UNDEF            /* quote next char */
  35. };
  36.  
  37. /*
  38.  * BUGS: in tos, turning ECHO off but leaving RAW and CBREAK alone doesn't
  39.  * work properly
  40.  */
  41.  
  42. long
  43. _read(fd, buf, size)
  44.     int fd;
  45.     void *buf;
  46.     unsigned long size;
  47. {
  48.     char *foo;
  49.     long r;
  50.     extern int __mint;
  51.     int indx;
  52.     int flags;
  53. #ifdef EIO
  54.     long tty_pgrp;
  55.     long omask;
  56.     __Sigfunc osigt;
  57. #endif
  58. #ifdef EAGAIN
  59.     long wasready;
  60. #endif
  61.  
  62.     if (isatty(fd)) {
  63. /* work around a bug in TOS; 4096 bytes should be plenty for terminal reads */
  64.         if (size > 4096) size = 4096;
  65.         indx = __OPEN_INDEX(fd);
  66.         if (indx < 0 || indx >= __NHANDLES)
  67.             indx = __NHANDLES - 1;
  68.         flags = __open_stat[indx].flags;
  69.     }
  70.     else
  71.         flags = -1;
  72.  
  73.     if ( (__mint > 0) || (flags  == -1) ||
  74.          ( ((flags & (RAW|CBREAK|ECHO)) == ECHO) ) ) {
  75. #ifdef EIO
  76.                 if (__mint && _isctty(fd)) {
  77.           (void) Fcntl(fd, (long) &tty_pgrp, TIOCGPGRP);
  78.           if (tty_pgrp != Pgetpgrp()) {
  79. #if 0
  80.             /* This isn't really what we mean here...we really want to
  81.                know if our process group has no controlling terminal.
  82.             */
  83.             if (fd == -1 && __open_stat[indx] == FH_ISAFILE) {
  84.               errno = EIO;
  85.               return -1;
  86.             }
  87. #endif
  88.             omask = Psigblock(~0L);
  89.             osigt = (__Sigfunc) Psignal(SIGTTIN, (long) SIG_IGN);
  90.             (void) Psignal(SIGTTIN, (long) osigt);
  91.             (void) Psigsetmask(omask);
  92.             if ((omask & sigmask(SIGTTIN)) || (osigt == SIG_IGN)) {
  93.               errno = EIO;
  94.               return -1;
  95.             }
  96.           }
  97.         }
  98. #endif /* EIO */
  99. #ifdef EAGAIN
  100.         if (__mint) {
  101.             (void)Fcntl(fd, &wasready, FIONREAD);
  102.         }
  103. #endif
  104.         r = Fread(fd, size, buf);
  105. #ifdef EAGAIN
  106.         if (__mint && r == 0 && wasready == 0
  107.             && (Fcntl(fd, 0, F_GETFL) | O_NDELAY)) {
  108.             r = -EAGAIN;
  109.         }
  110. #endif
  111.         if (r < 0) {
  112.             errno = (int) -r;
  113.             return -1;
  114.         }
  115.  
  116.     /* watch out for TTYs */
  117.         if (__mint == 0 && isatty(fd)) {
  118.             foo = (char *)buf;
  119.             if (*foo == __tchars.t_eofc) /* EOF character? */
  120.                 return 0;
  121.             /* for multibyte reads terminated by a CR, we add
  122.                the CR since TOS doesn't put it in for us
  123.                         */
  124.             if ((r < size)  && (foo[r - 1] != '\r'))
  125.             {
  126.                 foo[r] = '\r';
  127.                 r++;
  128.             }
  129.             /* If the last char is a CR (either added above
  130.                or read from a single-byte Fread()) we translate
  131.                it according to the CRMOD setting
  132.             */
  133.              if ((flags & CRMOD) && r && (foo[r - 1] == '\r')) {
  134.                  foo[r - 1] = '\n';
  135.                 Cconout('\n'); /* not quite right if fd != 0 */
  136.             }
  137.         }
  138.     }
  139.     else {
  140. again:
  141.         r = _console_read_byte(fd) & 0x00ff;
  142.         if (flags & ECHO) {
  143.             _console_write_byte(fd, (int)r);
  144.         }
  145.         if (flags & CRMOD) {
  146.             if (r == '\r') r = '\n';
  147.         }
  148.         if (!(flags & RAW)) {
  149.             if (r == __tchars.t_intrc) {
  150.                 raise(SIGINT);
  151.                 goto again;
  152.             }
  153.             else if (r == __tchars.t_quitc) {
  154.                 raise(SIGQUIT);
  155.                 goto again;
  156.             }
  157.         }
  158.         *((char *)buf) = r;
  159.         r = 1;
  160.     }
  161.  
  162.     return r;
  163. }
  164.  
  165. #if defined (__GNUC__) && !defined (__MSHORT__)
  166. __asm__ (".stabs \"_read\",5,0,0,__read");
  167. #else
  168. int
  169. read(fd, buf, size)
  170.     int fd;
  171.     void *buf;
  172.     unsigned size;
  173. {
  174.     return (int) _read(fd, buf, (unsigned long)size);
  175. }
  176. #endif
  177.